package com.qingcheng.config;

import com.qingcheng.pojo.goods.TbSku;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * @ClassName RedisCacheConfig
 * @Description
 * @Author Simon
 * @Date 2020/8/25 9:37
 * @Version 1.0
 **/
@Configuration
@Slf4j
public class RedisCacheConfig {

    /**
     * 自定义构建的redisTemplate容器
     * 接入到容器
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(name={"redisTemplate"})
    public RedisTemplate goodsRedisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        // 创建自定义序列化器
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        template.setDefaultSerializer(jackson2JsonRedisSerializer);
        return  template;
    }

    /**
     * 在RedisConfig配置类中使用@Bean注解注入了一个默认名称为方法名的cacheManager组件。
     * 在定义的Bean组件中，通过RedisCacheConfiguration对缓存数据的key和value分别进行了序列化方式的定制，
     * 其中缓存数据的key定制为StringRedisSerializer（即String格式），
     * 而value定制为了Jackson2JsonRedisSerializer（即JSON格式），
     * 同时还使用entryTtl(Duration.ofDays(1))方法将缓存数据有效期设置为1天
     * 完成基于注解的Redis缓存管理器RedisCacheManager定制后，
     * 可以对该缓存管理器的效果进行测试（使用自定义序列化机制的RedisCacheManager测试时，实体类可以不用实现序列化接口）
     * @param factory
     * @return
     */
    @Bean
    public RedisCacheManager skuCacheManager(RedisConnectionFactory factory){
        // 分别创建String和JSON格式序列化对象，对缓存数据key和value进行转换
        RedisSerializer strSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jacksonSeial =
                new Jackson2JsonRedisSerializer(Object.class);

        // 定制缓存数据序列化方式及时效
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))
                .serializeKeysWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(strSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(jacksonSeial))
                .disableCachingNullValues();
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();
        return redisCacheManager;
    }

}
